#ifndef _TRAVERSE_H_
#define _TRAVERSE_H_

#include "typelist.hpp"
#include "type_traits.hpp"

namespace Medved
{
	
template <class T, class Actor>
inline void traverseMembers(T &data, const Actor &actor);

namespace Private
{
	template <class Actor>
	class TraverseActor
	{
		const Actor &actor_;
		
	public:
		TraverseActor(const Actor &actor) :
			actor_(actor)
		{}
		
		template <class T1>
		const TraverseActor &operator &(T1 &data) const
		{
			traverseMembers(data, actor_);
			return *this;
		}
	};
	
	template <class T, class Actor>
	struct TraverseIn
	{
		static void invoke(T &data, const Actor &actor)
		{
			data.traverseMembers(TraverseActor<Actor>(actor));
		}
	};
	
	template <class T, class Actor>
	struct Apply
	{
		static void invoke(T &data, const Actor &actor)
		{
			actor(data);
		}
	};
}

template <class T, class Actor>
inline void traverseMembers(T &data, const Actor &actor)
{
	Select<TypeTraits<T>::isBuiltIn,
	Private::Apply<T, Actor>,
	Private::TraverseIn<T, Actor>	
	>::Result::invoke(data, actor);
}

}
#endif
